﻿

using InfluxDB.Client;

using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Core.Exceptions;
using IotClientService.Models.Option;
using IotContract.Interfaces.Db;
using IotContract.Models.InfluxDb;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Config;
using Mapster;
using InfluxDB.Client.Core;

namespace IotClientService.RealDbs;
public class InfluxDbService: IRealDbService
{
    private  RealDbOption _option;

    public InfluxDbService()
    {
        var realOption = AppSettings.GetObjData<RealDbOption>();
        _option = realOption;
    }

    private  InfluxDBClient CreateClient()
    {
        var builder = InfluxDBClientOptions.Builder.CreateNew();
        builder.Url(_option.ApiUrl);
       
        builder.AuthenticateToken(_option.Token);
       
        builder.LogLevel(LogLevel.None);
        builder.TimeOut(TimeSpan.FromSeconds(600));
        return new(builder.Build());
    }

    /// <summary>
    /// 初始化DB
    /// </summary>
    /// <returns></returns>
    public async Task<string> InitDb()
    {


       using var client= CreateClient();
        
       
        var flux = "from(bucket:\"test\") |> range(start: -1m)";

        try
        {
            var api = await client.GetQueryApi().QueryAsync(flux, "eve");
            return string.Empty;
        }
        catch(InfluxException  ex)
        {
            return ex.Message;
        }
        catch(HttpRequestException ex)
        {
            return "timeout " + ex.Message;
        }
       
    }
    /// <summary>
    /// 写入db
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="datas">数据</param>
    /// <param name="bucket">桶</param>
    /// <param name="org">组织</param>
    /// <returns></returns>
    public async Task<string> WriteDbs<T>(List<T> datas,string bucket,string org)
    {
        using var client = CreateClient();
        var writeApi = client.GetWriteApiAsync();
        try
        {
            if (datas.Count > 4000)
            {
                var groups = datas.Select((x, i) => new { Index = i, Value = x }).GroupBy(x => x.Index / 4000).Select(x => x.Select(v => v.Value).ToList()).ToList();

                foreach(var group in groups)
                {
                    await writeApi.WriteMeasurementsAsync(group, InfluxDB.Client.Api.Domain.WritePrecision.S, bucket, org);
                }
            }
            else
            {
                await writeApi.WriteMeasurementsAsync(datas, InfluxDB.Client.Api.Domain.WritePrecision.S, bucket, org);
            }

            
            return string.Empty;
        }
        catch (InfluxException ex)
        {
            return ex.Message;
        }

    }
    /// <summary>
    /// 查询数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task<List<T>> QueryDatas<T>(DbQuery query)
    {
        using var client = CreateClient();
        var queryApi = client.GetQueryApiSync();
        var datas= queryApi.QuerySync<T>(query.Flux, query.Org);
        return datas;
        
    }
    /// <summary>
    /// 查询数据
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task<List<object>> QueryDatas(DbQuery query)
    {
        using var client = CreateClient();
        var queryApi = client.GetQueryApiSync();
        var datas = queryApi.QuerySync(query.Flux, query.Org);
        List<object> result = new List<object>();
        datas.ForEach(x =>
        {
            result.AddRange(x.Records);
        });
        return result;

    }
    /// <summary>
    /// 删除数据库
    /// </summary>
    /// <param name="delete"></param>
    /// <returns></returns>
    public async Task<string> DeleteDbs(DbDelete delete)
    {
        //if (delete.Token != _option.Token)
        //{
        //    return "权限验证失败";
        //}
        using var client = CreateClient();
        var writeApi = client.GetDeleteApi(); 

        try
        {
            await writeApi.Delete(delete.StartTime, delete.StopTime, delete.Predicate, delete.Bucket, delete.Org);
            return string.Empty;
        }
        catch (InfluxException ex)
        {
            return ex.Message;
        }

    }
}
